from iutk import *
from sys import *
from string import *

################################################################################
# PARTIE ALGORITHMQUE
################################################################################

def lectureFichierMap(fichier):

    """renvoie une Matrice dont le premier élément est le titre et le deuxième est la matrice de la map"""
    
    mot=""
    ligne2=[]
    listeMap=[]
    matriceMap=[]
    matriceAll=[]
    save=fichier.readline()   
    matriceAll.append(save) #titre
    tmp=fichier.readline()  #high score
    save+=tmp
    tmp=tmp.strip()
    matriceAll.append(tmp)
     
    for ligne in fichier:

        save+=ligne
        ligne=ligne.strip()
        ligne2=ligne.split(",")
    
        for mot in ligne2:
            if mot=="":
                listeMap.append("Vide")
                mot=""
            elif mot=="Mur":
                listeMap.append("Mur")
                mot=""
            elif mot=="Trou":
                listeMap.append("Trou")
                mot=""
            elif mot=="Bloc":
                listeMap.append("Bloc")
                mot=""
            elif mot=="Cle":
                listeMap.append("Cle")
                mot=""
            elif mot=="Porte":
                listeMap.append("Porte")
                mot=""
            elif mot=="Start":
                listeMap.append("Start")
                mot=""
            elif mot=="BlocS":
                listeMap.append("BlocS")
                mot=""                
            elif mot=="\n":
                break
            
        matriceMap.append(listeMap*1)
        listeMap=[]
        
    matriceAll.append(matriceMap)
    matriceAll.append(save)         #sauvegarde

    return matriceAll

def listeTrou(matriceMap):
    
    """Renvoie la liste des coordonnées, dans la matrice, des trous"""

    lstTrou=[]
    for i in range(len(matriceMap)):
        for j in range(len(matriceMap[i])):
            if matriceMap[i][j]=='Trou':
                lstTrou.append([i,j])
    return lstTrou



def initialisationPersonnage(matriceMap):
    
    """ renvoie la position (dans la matrice) sous forme de liste du personnage au début du jeu """
    
    personnage=[]
    for x in range(len(matriceMap)):
        for y in range(len(matriceMap[x])):
            if matriceMap[x][y]=="Start":
                personnage=[x,y]

    return personnage



def deplacementBloc(matriceMap,emplacement,direc,lstCle):
    """Renvoie false si le bloc ne peut pas se déplacer sinon elle renvoie la nouvelle position sous forme de liste"""

    
    emplacement2=emplacement*1

    if direc=="Up":
        if emplacement2[0]!=0:
            emplacement2[0]-=1
        else:
            return False
    elif direc=="Down":
        if emplacement2[0]!=len(matriceMap)-1:
            emplacement2[0]+=1
        else:
            return False
    elif direc=="Right":
        if emplacement2[1]!=len(matriceMap[0])-1:
            emplacement2[1]+=1
        else:
            return False
    elif direc=="Left":
        if emplacement2[1]!=0:
            emplacement2[1]-=1
        else:
            return False

    x,y=emplacement2

    
    if matriceMap[x][y]=="Mur" or matriceMap[x][y]=="Bloc" or matriceMap[x][y]=="BlocS" or (matriceMap[x][y]=="Porte" and lstCle[0]==0) :
        return False
    if matriceMap[x][y]=="Porte" and lstCle[0]!=0:
        lstCle[0]-=1
        
    return emplacement2
        
    



def deplacementPersonnage(matriceMap,direc,emplacementPerso,lstCle):
    
    """Renvoie la position du personnage après avoir reçu la direction"""
    
    emplacementProvi=emplacementPerso*1
    emplacementBloc=[]

    #Détermination du futur emplacement du personnage
    
    if direc=="Up":
        if emplacementPerso[0]!=0:
            emplacementPerso[0]-=1
    elif direc=="Down":
        if emplacementPerso[0]!=len(matriceMap)-1:
            emplacementPerso[0]+=1
    elif direc=="Right":
        if emplacementPerso[1]!=len(matriceMap[0])-1:
            emplacementPerso[1]+=1
    elif direc=="Left":
        if emplacementPerso[1]!=0:
            emplacementPerso[1]-=1

    x,y=emplacementPerso
    x2,y2=emplacementProvi

    #Vérifie si le futur emplacement est valide 

    if matriceMap[x][y]=="Mur" or (matriceMap[x][y]=="Porte" and lstCle[0]==0):
        return emplacementProvi

    if matriceMap[x][y]=="Porte" and lstCle[0]!=0:
        matriceMap[x][y]="Vide"
        lstCle[0]-=1
        return emplacementPerso

    if matriceMap[x][y]=="Cle":
        lstCle[0]+=1
        matriceMap[x][y]="Vide"
        return emplacementPerso
        
    if matriceMap[x][y]=="Bloc" or matriceMap[x][y]=="BlocS":
        emplacementBloc=[x,y]
        tmp=deplacementBloc(matriceMap,emplacementBloc,direc,lstCle)
        if tmp==False:
            return emplacementProvi
        else:
            a,b=tmp
            matriceMap[a][b]=matriceMap[x][y]
            matriceMap[x][y]="Vide"
            return emplacementPerso
        
      
    else:
        return emplacementPerso
        


def deplacementBlocS(emplacementPerso,emplacementAvant,matriceMap,direction,blocS):
    """Gère le déplacement des blocs spéciaux (c'est à dire 'tirer')"""
    
    i,j=blocS
    emplacementBlocS=[i,j]
    tmp2=False
    x,y=emplacementAvant
    x2,y2=emplacementPerso
                    
    if direction=="Up" and i-1==x and j==y and (x!=x2 or y!=y2):
        emplacementBlocS=emplacementAvant*1
        tmp2=True
                        
    elif direction=="Down" and i+1==x and j==y and (x!=x2 or y!=y2):
        emplacementBlocS=emplacementAvant*1
        tmp2=True
                        
    elif direction=="Left" and j-1==y and i==x and (x!=x2 or y!=y2):
        emplacementBlocS=emplacementAvant*1
        tmp2=True
                        
    elif direction=="Right" and j+1==y and i==x and (x!=x2 or y!=y2):
        emplacementBlocS=emplacementAvant*1
        tmp2=True
                        
    if tmp2!=False:
        a,b=emplacementBlocS
        matriceMap[a][b]="BlocS"
        matriceMap[i][j]="Vide"
                     
    
def initialiserBoutonMenu(largeurMenu, hauteurMenu):

    ''' Initialise les boutons du menu : jouer, éditer '''
    
    menu = {}

    # Bouton Jouer
    x, y = hauteurMenu//2-75, largeurMenu//2-75
    largeur, hauteur = x+150, y+50
    menu['jouer'] = [x, y, largeur, hauteur]

    # Bouton Editer
    x, y = x, hauteur+20
    largeur, hauteur = x+150, y+50
    menu['editer'] = [x, y, largeur, hauteur]

    return menu
    

def initialiserBoutonJeu(hauteurFenetre, largeurFenetre):

    ''' Initialise les boutons en jeu :
        - menu
        - reset
        - score
        - undo
        - quit
        -highscore
    '''

    bouton = {}

    # Bouton Menu
    x, y = 10, hauteurFenetre+10
    largeur, hauteur = 130, y+40
    bouton['menu'] = [x, y, largeur, hauteur]

    # Bouton Reset
    x, y = x, hauteur+5
    largeur, hauteur = largeur, y+40
    bouton['reset'] = [x, y, largeur, hauteur]

    # Score
    x, y = x, hauteur+5
    largeur, hauteur = largeur, y+40
    bouton['score'] = [x, y, largeur, hauteur]

    # Bouton Undo
    x, y = largeurFenetre//2, hauteurFenetre+10
    largeur, hauteur = x+130, y+40
    bouton['undo'] = [x, y, largeur, hauteur]

    # Bouton Quit
    x, y = x, hauteur+5
    largeur, hauteur = largeur, y+40
    bouton['quit'] = [x, y, largeur, hauteur]

    # Highcore
    x, y = x, hauteur+5
    largeur, hauteur = largeur, y+40
    bouton['highscore'] = [x, y, largeur, hauteur]

    return bouton

def initialiserBoutonsEditeur(hauteurFenetre, largeurFenetre):
    
    ''' Initialise les boutons d'édition '''

    bouton = {}

    # Bouton Menu
    x, y = 10, hauteurFenetre+10
    largeur, hauteur = 130, y+30
    bouton['menu'] = [x, y, largeur, hauteur]

    # Bouton Open
    x, y = x, hauteur+5
    largeur, hauteur = largeur, y+30
    bouton['open'] = [x, y, largeur, hauteur]

    # Bouton Save
    x, y = x, hauteur+5
    largeur, hauteur = largeur, y+30
    bouton['save'] = [x, y, largeur, hauteur]

    # Bouton Quit
    x, y = x, hauteur+5
    largeur, hauteur = largeur, y+30
    bouton['quit'] = [x, y, largeur, hauteur]
    

    ''' Couleurs et valeurs des blocs '''

    #Bouton Mur
    x, y = largeurFenetre//2+10, hauteurFenetre+10
    largeur, hauteur = x+110, y+30
    bouton['Mur'] = [x, y, largeur, hauteur]

    # Bouton Bloc    
    x, y = x, y+35
    largeur, hauteur = x+110, y+30
    bouton['Bloc'] = [x, y, largeur, hauteur]

    # Bouton Porte    
    x, y = x, y+35
    largeur, hauteur = x+110, y+30
    bouton['Porte'] = [x, y, largeur, hauteur]

    # Bouton Vide    
    x, y = x, y+35
    largeur, hauteur = x+110, y+30
    bouton['Vide'] = [x, y, largeur, hauteur]

    #Bouton Trou
    x, y = largeurFenetre-largeurFenetre//4+10, hauteurFenetre+10
    largeur, hauteur = x+110, y+30
    bouton['Trou'] = [x, y, largeur, hauteur]

    # Bouton Cle    
    x, y = x, y+35
    largeur, hauteur = x+110, y+30
    bouton['Cle'] = [x, y, largeur, hauteur]

    # Bouton Blocs    
    x, y = x, y+35
    largeur, hauteur = x+110, y+30
    bouton['BlocS'] = [x, y, largeur, hauteur]

    # Bouton Start   
    x, y = x, y+35
    largeur, hauteur = x+110, y+30
    bouton['Start'] = [x, y, largeur, hauteur]   

    return bouton

def initialiserBoutonsConfirmation(hauteurMenu, largeurMenu):

    ''' Initialise les boutons de confirmation avant l'édition '''
    
    boutons = {}

    # Oui
    x, y = 10, hauteurMenu+60
    largeur, hauteur = x+130, y+40
    boutons['oui'] = [x, y, largeur, hauteur]

    # Menu
    x, y = 150, hauteurMenu+60
    largeur, hauteur = x+130, y+40
    boutons['menu'] = [x, y, largeur, hauteur]

    # Open
    x, y = largeur+10, hauteurMenu+60
    largeur, hauteur = x+130, y+40
    boutons['open'] = [x, y, largeur, hauteur]

    return boutons

def coordBoutons(boutons, ev):

    ''' Renvoie, si c'en est un, la valeur du bouton selectionné '''
    
    try:
        x, y = ev

        for i in boutons:
            if x >= boutons[i][0]:
                if x <= boutons[i][2]:
                    if y >= boutons[i][1]:
                        if y <= boutons[i][3]:
                            return i
        return 'None'
    
    except:
        return 'None'

def coordEditeur(ev, largeurFenetre, hauteurFenetre, definition):

    ''' Renvoie la coord de la case selectionné dans l'éditeur '''
    
    x, y = ev
    
    for i in range(0, largeurFenetre, definition):
        for j in range(0, hauteurFenetre, definition):
            if x >= i and x < i+definition:
                if y >= j and y < j+definition:
                    coord = j//definition, i//definition
                    return coord
    return 'None'


def procheBlocS(perso,matriceMap):
    
    """Renvoie les coordonnées du blocS si le personnage est à coté d'un bloc spécial"""
    
    x,y=perso
    lst=[]
    
    if x<len(matriceMap)-1 and matriceMap[x+1][y]=="BlocS":
        lst.append([x+1,y])
       
    if x>0 and matriceMap[x-1][y]=="BlocS":
            lst.append([x-1,y])
       
    if y<len(matriceMap[x])-1 and matriceMap[x][y+1]=="BlocS":
        lst.append([x,y+1])
        
    if y>0 and matriceMap[x][y-1]=="BlocS":
        lst.append([x,y-1])

    if len(lst)==0:
        return False
    
    return lst

def copierMatrice(matrice):

    ''' Fait une copie de la matrice donnée en paramètre '''
    
    nouvelle = []
    for val in matrice:
        nouvelle.append(val)
    return nouvelle

def copierMap(map):

    ''' Copie la carte donnée en paramètre '''
    
    new = []
    for i in range(len(map)):
        new.append([])
        for j in range(len(map[i])):
            new[i].append(map[i][j])
    return new


def tailleTableau(largeurFenetre, hauteurFenetre, definition, val=True):

    ''' Renvoie la taille de la grille souhaitée dans l'éditeur '''

    if val == True:
        x, y = clic()
        a, b = -1, -1
        for i in range(0, largeurFenetre, definition):
            if x >= i and x < i+definition:
                a = i

        for j in range(0, hauteurFenetre+definition, definition):
            if y >= j and y < j+definition:
                b = j

        if -1 in [a, b]:
            return tailleTableau(largeurFenetre, hauteurFenetre, definition)

        val = a, b
        return val

    else:
        x, y = val

        a, b = -1, -1
        
        for i in range(0, largeurFenetre, definition):
            if x >= i and x < i+definition:
                a = i

        for j in range(0, hauteurFenetre+definition, definition):
            if y >= j and y < j+definition:
                b = j

        val = a, b
        
        return val        

def creerMap(caseX, caseY):
    
    """ Construit une map vide (pour l'éditeur) """
    
    tab = []
    
    for i in range(caseY+1):
        tab.append([])
        for j in range(caseX+1):
            tab[i].append('')
    return tab    

def transposerMatriceMap(matriceMap):
    
    """ Retourne la map de manière textuelle """    
    
    ma_map = 'Titre : "Map"\n?\n'
    
    for i in range(len(matriceMap)):
        for j in range(len(matriceMap[i])):
            if j == len(matriceMap[i])-1:
                if matriceMap[i][j] == 'Vide':
                    ma_map += ''
                else:
                    ma_map += matriceMap[i][j]
                
            else:
                if matriceMap[i][j] == 'Vide':
                    ma_map += ''+',' 
                else:
                    ma_map += matriceMap[i][j]+','                      
            
        ma_map += '\n'

    return ma_map


def mapEstJouable(map):
    
    """ Vérifie si la map créer par l'utilisateur est jouable """
    
    nbTrou = 0
    nbBloc = 0
    start = False

    for i in range(len(map)):
        for j in range(len(map[i])):
            if map[i][j] in ['Bloc', 'BlocS']:
                nbBloc += 1
            elif map[i][j] == 'Start':
                if start == False:
                    start = True
                elif start == True:
                    return False
            elif map[i][j] == 'Trou':
                nbTrou += 1

    return (nbTrou == nbBloc) and start


def verifGagne(matriceMap, lstTrou):
    
    """ Vérifie si l'utilisateur a gagné la partie """
    blocs = []
    for i in range(len(matriceMap)):
        for j in range(len(matriceMap[i])):
            if matriceMap[i][j] in ['Bloc','BlocS']:
                blocs.append([i, j])

    for i in lstTrou:
        if i not in blocs:
            return False

    return True
            
def remplacerRecord(mapTexte,record):
    
    """ Renvoie la map textuelle avec le record modifié """
    
    rang=0
    a=0
    ligne1=-1
    for i in mapTexte:
        if a==0:
            ligne1+=1
        try:
            if i=="?":
                rang+=1
                break
            else:    
                a=int(i)
                rang+=1
        except:
            continue
        
    nouvelleMapTexte=mapTexte[:ligne1]+str(record)+mapTexte[ligne1+rang:]

    return nouvelleMapTexte
            
################################################################################
# PARTIE GRAPHIQUE
################################################################################

def afficherGrille(largeurFenetre, hauteurFenetre, definition):
    
    """ affiche la grille sur la map """
    
    for i in range(0, largeurFenetre+definition, definition):
        ligne(i, 0, i, hauteurFenetre)

    for j in range(0, hauteurFenetre+definition, definition):
        ligne(0, j, largeurFenetre, j)

def afficherMap(map, definition):
    
    """ Affiche la map avec une partie de ses éléments """
    
    for i in range(len(map)):
        for j in range(len(map[i])):
            y = i*definition
            x = j*definition

            if map[i][j] == 'Trou':
                rectanglePlein(x, y, x+definition, y+definition, 'black')

            if map[i][j] == 'Start':
                rectanglePlein(x, y, x+definition, y+definition, 'green')

            elif map[i][j] == 'Cle':
                
                x = x+definition//2
                y = y+definition//2
                cerclePlein(x, y, definition//2-2, 'yellow')                

            elif map[i][j] == 'Mur':
                rectanglePlein(x, y, x+definition, y+definition, 'brown')

            elif map[i][j] == 'Bloc':
                rectanglePlein(x, y, x+definition, y+definition, 'red')

            elif map[i][j] == 'Porte':
                rectanglePlein(x, y, x+definition, y+definition, 'blue')

            elif map[i][j] == 'BlocS':
                rectanglePlein(x, y, x+definition, y+definition, 'purple')
                

def afficherPerso(perso, definition):
    
    """ Affiche le personnage sur la map """
    
    y = perso[0]*definition
    x = perso[1]*definition

    x = x+definition//2
    y = y+definition//2

    cerclePlein(x, y, definition//2-2, 'orange')

def afficheTrou(lstTrou, definition):
    
    """Affiche les trous sur la map"""

    for i in range(len(lstTrou)):
        y = lstTrou[i][0]*definition
        x = lstTrou[i][1]*definition
        rectanglePlein(x, y, x+definition, y+definition, 'black')       
        
    
def afficherBouton(boutons, score=None, highscore=None):
    
    ''' Affiche les boutons '''

    for val in boutons:
        
        x, y, largeur, hauteur = boutons[val]

        if val == 'score' and score != None:
            tmp = str(val)+' : '+str(score)
            texte(x, y, tmp, 'black')

        elif val == 'highscore' and score != None:
            tmp = str(val)+' : '+str(highscore)
            texte(x, y, tmp, 'black')

        else:
            if val == 'Mur':
                rectanglePlein(x, y, largeur, hauteur, 'brown')

            elif val == 'Bloc':
                rectanglePlein(x, y, largeur, hauteur, 'red')

            elif val == 'Porte':
                rectanglePlein(x, y, largeur, hauteur, 'blue')

            elif val == 'Trou':
                rectanglePlein(x, y, largeur, hauteur, 'black')

            elif val == 'Cle':
                rectanglePlein(x, y, largeur, hauteur, 'yellow')

            elif val == 'BlocS':
                rectanglePlein(x, y, largeur, hauteur, 'purple')

            elif val == 'Start':
                rectanglePlein(x, y, largeur, hauteur, 'green')

            elif val not in ['score', 'highscore']:
                rectanglePlein(x, y, largeur, hauteur, 'white')
            rectangle(x, y, largeur, hauteur)

            if val != 'Trou':
                texteCentre(x+(largeur-x)//2, y+(hauteur-y)//2, val, 'black')
            else:
                texteCentre(x+(largeur-x)//2, y+(hauteur-y)//2, val, 'white')



def afficherZone(caseX, caseY, definition):
    
    """ Affiche la zone sélectionner (pour l'éditeur) """
    
    for i in range(0, caseX+definition, definition):
        for j in range(0, caseY+definition, definition):
            rectanglePlein(i, j, i+definition, j+definition, 'blue')


 
            
    

